﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using StackExchange.Redis;

// ReSharper disable once CheckNamespace
namespace km_sso_library
{
    /// <summary>
    /// 使用Redis保存缓存
    /// </summary>
    public static class RedisCache {

		private static RedisClient _rcClient;
		//private const string Prefix = "km:c:";
        private const string Prefix = "kmsso:";
        static RedisClient Client => _rcClient ?? (_rcClient = new RedisClient(ConfigurationHelper.Get<int>("redis-cache-index", 8)));
        //static RedisClient Client = new RedisClient();
        private static string GetKey(string key) {
            //return $"{Prefix}{(ConfigurationHelper.Get("isDebug", false) ? "t" : "d")}:{key}";
            return $"{Prefix}{key}";
        }

		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">基本类型（int，float。。。）</param>
		/// <param name="minutes"></param>
		public static RedisValue Add(string key, RedisValue value, int minutes) {
			Client.SetString(GetKey(key), value, minutes);
			return value;
		}
		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">基本类型（int，float。。。）</param>
		/// <param name="minutes"></param>
		public static void AddString(string key, string value, int minutes) {
			Client.SetString(GetKey(key), value, minutes);
		}
		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">基本类型（int，float。。。）</param>
		/// <param name="ts"></param>
		/// <returns></returns>
		public static RedisValue Add(string key, RedisValue value, TimeSpan ts) {
			Client.SetString(GetKey(key), value, ts);
			return value;
		}
		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <param name="ts"></param>
		/// <returns></returns>
		public static string AddString(string key, string value, TimeSpan ts) {
			Client.SetString(GetKey(key), value, ts);
			return value;
		}
		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <param name="ts"></param>
		/// <returns></returns>
		public static int AddInt(string key, int value, TimeSpan ts) {
			Client.SetString(GetKey(key), value, ts);
			return value;
		}
		/// <summary>
		/// 添加一个项目到Redis 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <param name="minutes"></param>
		/// <returns></returns>
		public static int AddInt(string key, int value, int minutes) {
			Client.SetString(GetKey(key), value, minutes);
			return value;
		}
		/// <summary>
		/// 添加一个项目到Redis
		/// 如果key已经存在则覆盖
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">必须可序列化</param>
		/// <param name="minutes"></param>
		public static T AddObject<T>(string key, T value, int minutes) {
			Client.GetDatabase().SetString(GetKey(key), value, TimeSpan.FromMinutes(minutes));
			return value;
		}
		/// <summary>
		/// 永久存储数据
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">基本类型</param>
		public static RedisValue Max(string key, RedisValue value) {
			Client.SetString(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 永久存储数据
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">可以序列号的对象</param>
		public static object Max(string key, object value) {
			Client.GetDatabase().SetString(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 永久存储数据
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">可以序列号的对象</param>
		public static long MaxLong(string key, long value) {
			Client.AddLong(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 永久存储数据
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">可以序列号的对象</param>
		public static void MaxString(string key, string value) {
			Client.AddString(GetKey(key), value);
		}
		/// <summary>
		/// 重置超时时间
		/// </summary>
		/// <param name="key"></param>
		/// <param name="minutes"></param>
		public static void Expire(string key,int minutes){
			Client.Expire(GetKey(key), minutes);
		}

		#region SET
		/// <summary>
		/// 永久存储IEnumerable&lt;T&gt;数据（集合SET）
		/// 添加一个列表到SET
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void MaxSetList<T>(string key, IEnumerable<T> value) where T : class, new() {
			foreach (var item in value) {
				Client.GetDatabase().SetSet(GetKey(key), item);
			}
		}
		/// <summary>
		/// 永久存储T数据（集合SET）
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void MaxSetListAdd<T>(string key, T value) where T : class, new() {
			Client.GetDatabase().SetSet(GetKey(key), value);
		}
		/// <summary>
		/// 永久存储T数据（集合SET）
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void MaxSetListAdd(string key, string value){
			Client.AddValueToSet(GetKey(key), value);
		}
		/// <summary>
		/// 永久存储IEnumerable&lt;RedisValue&gt;数据（集合SET）
		/// 添加一个列表到SET
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void MaxSetList(string key, IEnumerable<RedisValue> value) {
			foreach (var item in value) {
				Client.AddValueToSet(GetKey(key), item);
			}
		}
		/// <summary>
		/// 永久存储Object数据（集合SET）
		/// 把传入的value添加到SET（key指定的）里面
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static object MaxSetAdd(string key, object value) {
			Client.GetDatabase().SetSet(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 永久存储Object数据（集合SET）
		/// 把传入的value添加到SET（key指定的）里面
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static object MaxSetAddInt(string key, int value) {
			Client.AddValueToSet(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 永久存储RedisValue数据（集合SET）
		/// 把传入的value添加到SET（key指定的）里面
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static RedisValue MaxSetAdd(string key, RedisValue value) {
			Client.AddValueToSet(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static string MaxSetAddString(string key, string value) {
			Client.AddValueToSet(GetKey(key), value);
			return value;
		}
		#endregion

		#region LIST

		/// <summary>
		/// 从LIST中读取 字符串列表
		/// </summary>
		/// <param name="pKey"></param>
		/// <param name="skip"></param>
		/// <param name="limit"></param>
		/// <returns></returns>
		public static IEnumerable<string> GetListList(string pKey, int skip, int limit) {
			if (!Exists(pKey)){
				return new string[] { };
			}
			var qs = Client.GetList(GetKey(pKey), skip, skip + limit).ToList();
			return qs.Any()
				? qs.Select(s => s.ToString())
				: new string[] { };

		}
		/// <summary>
		/// 从LIST中读取数据并移除
		/// </summary>
		/// <param name="pKey"></param>
		/// <param name="count"></param>
		/// <returns></returns>
		public static IEnumerable<string> ListLeftPop(string pKey, int count){
			if (!Exists(pKey)) {
				return new string[] { };
			}
			var db = Client.GetDatabase();
			var theKey = GetKey(pKey);
			var length = db.ListLength(theKey);
			var reslut = new List<string>();
			for (var i = 0; i < count && i < length; i++){
				reslut.Add(db.ListLeftPop(theKey));
			}
			
			return reslut;
		}

		/// <summary>
		/// 添加到列表，尾部（右边）
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static T MaxListAdd<T>(string key, T value) where T : class, new(){
			Client.GetDatabase().ListRightPush(GetKey(key), Serialize(value));
			return value;
		}
		/// <summary>
		/// 添加到列表，尾部（右边）
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static string MaxListAdd(string key, string value){
			Client.GetDatabase().ListRightPush(GetKey(key), value);
			return value;
		}
		/// <summary>
		/// 把列表顶部（左边）的值取出
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <returns></returns>
		public static T ListPop<T>(string key) where T : class, new(){
			var value = Client.GetDatabase().ListLeftPop(GetKey(key));
			return Deserialize<T>(value);
		}
		/// <summary>
		/// 把列表顶部（左边）的值取出
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static string ListPopString(string key)  {
			var value = Client.GetDatabase().ListLeftPop(GetKey(key));
			return value;
		}
		/// <summary>
		///  返回一个LIST的“长度”
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static long CountList(string key){
			return Client.GetListLength(GetKey(key));
		}

		#endregion

		#region Hash
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="field"></param>
		/// <param name="value"></param>
		public static void AddHash(string hashKey, string field, RedisValue value){
			Client.HashSet(GetKey(hashKey), field, value);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="field"></param>
		/// <param name="value"></param>
		public static void HashAdd(string hashKey, int field, object value) {
			var db = Client.GetDatabase();
			db.HashSet(GetKey(hashKey), field, (RedisValue)value);
		}
		public static void HashAddIntString(string hashKey, int field, string value) {
			var db = Client.GetDatabase();
			db.HashSet(GetKey(hashKey), field, value);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="field"></param>
		/// <param name="value"></param>
		public static void HashAdd(string hashKey, long field, object value) {
			var db = Client.GetDatabase();
			db.HashSet(GetKey(hashKey), field, (RedisValue)value);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="field"></param>
		/// <param name="value"></param>
		public static void HashAdd(string hashKey, string field, object value) {
			var db = Client.GetDatabase();
			db.HashSet(GetKey(hashKey), field, (RedisValue)value);
		}
        public static void HashAdd(string hashKey, string field, string value) {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, value);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <param name="minutes"></param>
        public static void AddHash(string hashKey, string field, RedisValue value, int minutes) {
			Client.HashSet(GetKey(hashKey), field, value);
			Expire(hashKey, minutes);
		}
        public static void RemoveHash(string hashKey, int field) {
            Client.GetDatabase().HashDelete(GetKey(hashKey), field);
        }
        public static void RemoveHash(string hashKey, string field) {
            Client.GetDatabase().HashDelete(GetKey(hashKey), field);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static RedisValue GetHash(string hashKey, string field, RedisValue dv){
			return Client.HashGet(GetKey(hashKey), field, dv);
		}
        public static IDictionary<string, string> GetAllHashStr(string hashKey) {
            if (!Exists(hashKey))
                return null;
            var list = Client.GetDatabase().HashGetAll(GetKey(hashKey));
            var dict = new Dictionary<string, string>();
            foreach (var item in list) {
                dict.Add((string)item.Name, (string)item.Value);
            }
            return dict;
        }
        public static IDictionary<int,string> GetAllHashIntStr(string hashKey) {
            if (!Exists(hashKey))
                return null;
            var list = Client.GetDatabase().HashGetAll(GetKey(hashKey));
            var dict = new Dictionary<int, string>();
            foreach (var item in list) {
                dict.Add((int)item.Name, (string)item.Value);
            }
            return dict;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string GetHashString(string hashKey, string field, string dv) {
			return Client.HashGet(GetKey(hashKey), field, dv);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="field"></param>
		/// <param name="dv"></param>
		/// <returns></returns>
		public static string GetHashString(string hashKey, int field, string dv) {
			return Client.HashGet(GetKey(hashKey), field, dv);
		}

		#endregion

		/// <summary>
		/// 判断是否存在key
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static bool Exists(string key) {
			return Client.KeyExists(GetKey(key));
		}
		/// <summary>
		/// 判断hash里面key是否存在
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="key"></param>
		/// <returns></returns>
		public static bool HashExists(string hashKey, string key) {
			if (!Exists(hashKey)) {
				return false;
			}
			return Client.GetDatabase().HashExists(GetKey(hashKey), key);
		}
		/// <summary>
		/// 判断hash里面key是否存在
		/// </summary>
		/// <param name="hashKey"></param>
		/// <param name="key"></param>
		/// <returns></returns>
		public static bool HashExists(string hashKey, int key) {
			if (!Exists(hashKey)) {
				return false;
			}
			return Client.GetDatabase().HashExists(GetKey(hashKey), key);
		}
		/// <summary>
		/// 判断 item 是否存在SET（key）中
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool SetExists(string key, RedisValue value) {
			return Exists(key) && Client.IsItemExists(GetKey(key), value);
		}
		/// <summary>
		/// 判断 item 是否存在SET（key）中
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool SetExistsInt(string key, int value) {
			return Exists(key) && Client.IsItemExists(GetKey(key), value);
		}
        /// <summary>
		/// 判断 item 是否存在SET（key）中
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool SetExistsString(string key, string value) {
            return Exists(key) && Client.IsItemExists(GetKey(key), value);
        }
        /// <summary>
        /// 从Redis缓存中读取数据（基本类型）
        /// key不存在则返回dv
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static RedisValue Get(string key, RedisValue dv) {
			return Client.GetString(GetKey(key), dv);
		}
		/// <summary>
		/// 从Redis缓存中读取数据（基本类型）
		/// key不存在则返回nil
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static RedisValue Get(string key) {
			return Client.GetString(GetKey(key));
		}
		/// <summary>
		/// 从Redis缓存中获取JSON字符串并转换为数据对象
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <returns></returns>
		public static T GetAndDecodeJson<T>(string key) {
			if (!Exists(key))
				return default(T);
			var str = (string)Client.GetString(GetKey(key));
			return str.FromJson<T>();
		}
		/// <summary>
		/// 从Redis缓存中获取字符串
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static string GetString(string key) {
			return Client.GetString(GetKey(key));
		}
		/// <summary>
		/// 从Redis缓存中获取字符串
		/// </summary>
		/// <param name="key"></param>
		/// <param name="dv"></param>
		/// <returns></returns>
		public static string GetString(string key, string dv) {
			return Client.GetString(GetKey(key), dv);
		}

		/// <summary>
		/// 从Redis缓存中获取字符串
		/// </summary>
		/// <param name="key"></param>
		/// <param name="dv"></param>
		/// <returns></returns>
		public static string Get(string key, string dv) {
			return Client.GetString(GetKey(key), dv);
		}

		/// <summary>
		/// 从Redis缓存中获取 Int
		/// </summary>
		/// <param name="key"></param>
		/// <param name="dv"></param>
		/// <returns></returns>
		public static int GetInt(string key, int dv) {
			return Client.GetInt(GetKey(key), dv);
		}
		/// <summary>
		/// 从Redis缓存中读取数据（对象--可系列化）
		/// key不存在则返回dv
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <param name="dv"></param>
		/// <returns></returns>
		public static T Get<T>(string key, T dv) where T : class, new() {
			return Exists(key)
				? Deserialize<T>(Client.GetString(GetKey(key), new byte[] { }))
				: dv;
		}
		/// <summary>
		/// 从Redis缓存中读取一组数据（对象--可系列化）
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="pattern"></param>
		/// <param name="count"></param>
		/// <returns></returns>
		public static IEnumerable<T> GetList<T>(string pattern, int count) where T : class, new() {
			if (Count(pattern) < 1) return new List<T>();
			var keys = Client.GetKeys(GetKey(pattern), count);
			var result = new List<T>();
			foreach (var key in keys) {
				result.Add(Get<T>(key));
			}
			return result;
		}

		/// <summary>
		/// 从Redis缓存中读取数据（对象）
		/// 如果key不存在则返回null
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <returns></returns>
		public static T Get<T>(string key) where T : class, new() {
			return Exists(key)
				? Deserialize<T>(Client.GetString(GetKey(key), new byte[] { }))
				: null;
		}
		/// <summary>
		/// 从Redis缓存中读取数据（SET）
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="key"></param>
		/// <returns></returns>
		public static List<T> GetSet<T>(string key) where T : class, new() {
			if (!Exists(key)) {
				return null;
			}
			var count = Client.GetSetLength(GetKey(key));
			var result = new List<T>();
			if (count < 1000) {
				var values = Client.GetDatabase().SetMembers(GetKey(key));
				foreach (var item in values) {
					result.Add(Deserialize<T>(item));
				}
			} else {
				var loop = true;
				var ps = 1000;
				var off = 0;
				var cursor = 0L;
				while (loop) {
					var list = Client.GetDatabase().SetScan(GetKey(key),
						cursor: cursor,
						pageSize: ps,
						pageOffset: off
						);
					foreach (var item in list) {
						result.Add(Deserialize<T>(item));
					}
					var ic = list as IScanningCursor;
					loop = ic != null && ic.Cursor > 0;
					if (ic != null) {
						ps = ic.PageSize;
						off = ic.PageOffset;
						cursor = ic.Cursor;
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 从Redis缓存中读取数据（SET）
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static IList<int> GetSetInt(string key){
			if (!Exists(key)) {
				return null;
			}
			var count = Client.GetSetLength(GetKey(key));
			var result = new List<int>();
			if (count < 1000) {
				var values = Client.GetDatabase().SetMembers(GetKey(key));
				foreach (var item in values) {
					result.Add((int)item);
				}
			} else {
				var loop = true;
				var ps = 1000;
				var off = 0;
				var cursor = 0L;
				while (loop) {
					var list = Client.GetDatabase().SetScan(GetKey(key),
						cursor: cursor,
						pageSize: ps,
						pageOffset: off
						);
					foreach (var item in list) {
						result.Add((int)item);
					}
					var ic = list as IScanningCursor;
					loop = ic != null && ic.Cursor > 0;
					if (ic != null) {
						ps = ic.PageSize;
						off = ic.PageOffset;
						cursor = ic.Cursor;
					}
				}
			}
			return result;
		}
		/// <summary>
		/// 从Redis缓存中读取数据（SET）
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static IList<string> GetSetString(string key) {
			if (!Exists(key)) {
				return null;
			}
			var count = Client.GetSetLength(GetKey(key));
			var result = new List<string>();
			if (count < 1000) {
				var values = Client.GetDatabase().SetMembers(GetKey(key));
				foreach (var item in values) {
					result.Add((string)item);
				}
			} else {
				var loop = true;
				var ps = 1000;
				var off = 0;
				var cursor = 0L;
				while (loop) {
					var list = Client.GetDatabase().SetScan(GetKey(key),
						cursor: cursor,
						pageSize: ps,
						pageOffset: off
						);
					foreach (var item in list) {
						result.Add((string)item);
					}
					var ic = list as IScanningCursor;
					loop = ic != null && ic.Cursor > 0;
					if (ic != null) {
						ps = ic.PageSize;
						off = ic.PageOffset;
						cursor = ic.Cursor;
					}
				}
			}
			return result;
		}
		/// <summary>
		/// 从Redis缓存中移除数据
		/// </summary>
		/// <param name="key"></param>
		public static void Remove(string key) {
			Client.RemoveKey(GetKey(key));
		}
        /// <summary>
        /// 从Redis缓存中移除数据（模糊搜索）
        /// </summary>
        /// <param name="pattern"></param>
	    public static void RemoveByPattern(string pattern){
	        Client.RemoveKeysByPattern(pattern);
	    }

	    /// <summary>
        /// 从Redis缓存中移除RedisValue数据(SET)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void RemoveSet(string key, RedisValue value) {
			if (!Exists(key)) {
				return;
			}
			Client.GetDatabase().SetRemove(GetKey(key), value);
		}
		/// <summary>
		/// 从Redis缓存中移除Object数据(SET)
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void RemoveSet(string key, object value) {
			if (!Exists(key)) {
				return;
			}
			Client.GetDatabase().SetRemove(GetKey(key), Serialize(value));
		}
		/// <summary>
		/// 从Redis缓存中移除Object数据(SET)
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void RemoveSetInt(string key, int value) {
			if (!Exists(key)) {
				return;
			}
			Client.RemoveValueFromSet(GetKey(key), value);
		}
		/// <summary>
		/// 从Redis缓存中移除Object数据(SET)
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void RemoveSetString(string key, string value) {
			if (!Exists(key)) {
				return;
			}
			Client.RemoveValueFromSet(GetKey(key), value);
		}
		/// <summary>
		/// 统计关键字（Key）的数量
		/// </summary>
		/// <param name="pattern"></param>
		/// <returns></returns>
		public static long Count(string pattern) {
			return Client.Count(GetKey(pattern));
		}

		/// <summary>
		/// 搜索关键字
		/// </summary>
		/// <param name="pattern"></param>
		/// <param name="page"></param>
		/// <param name="limit"></param>
		/// <returns></returns>
		public static IEnumerable<string> GetKeys(string pattern, int page, int limit)
		{
			return Client.GetKeys(GetKey(pattern), page, limit).Select(s=>s.ToString()).ToList();
		}
		public static IEnumerable<string> GetKeys(string pattern, int limit) {
			return Client.GetKeys(GetKey(pattern), limit).Select(s => s.ToString()).ToList();
		}

		/// <summary>
		/// 获取指定集合（SET）的值得数量
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public static long SetCount(string key) {
			return Client.GetSetLength(GetKey(key));
		}
        /// <summary>
        /// 插入原子
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
	    public static long MaxIncrement(string key){
            var db = Client.GetDatabase();
            key = GetKey(key);
	        var r = db.StringIncrement(key);
	        return r;
	    }
        public static long MinusIncrement(string key,int pValue) {
            var db = Client.GetDatabase();
            key = GetKey(key);
            var r = db.StringDecrement(key, pValue);
            return r;
        }

        #region Helper
        /// <summary>
        /// 设置String
        /// </summary>
        /// <param name="dataBase"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan"></param>
        public static void SetString(this IDatabase dataBase, string key, object value, TimeSpan? timeSpan = null) {
			if (value == null) throw new ArgumentNullException("key");
			dataBase.StringSet(key, Serialize(value), timeSpan);
		}
		/// <summary>
		/// 设置SET
		/// </summary>
		/// <param name="dataBase"></param>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void SetSet(this IDatabase dataBase, string key, object value) {
			if (value == null) throw new ArgumentNullException("key");
			dataBase.SetAdd(key, Serialize(value));
		}
		static T Deserialize<T>(byte[] stream) where T : class, new() {
			if (stream == null) {
				return null;
			}
			var binaryFormatter = new BinaryFormatter();
			using (var memoryStream = new MemoryStream(stream)) {
				var result = (T)binaryFormatter.Deserialize(memoryStream);
				return result;
			}
		}
		static byte[] Serialize(object o) {
			if (o == null) {
				return null;
			}
			var binaryFormatter = new BinaryFormatter();
			using (var memoryStream = new MemoryStream()) {
				binaryFormatter.Serialize(memoryStream, o);
				var objectDataAsStream = memoryStream.ToArray();
				return objectDataAsStream;
			}
		}
		#endregion
	}
}
